#include <cppunit/config/SourcePrefix.h>

#include "TestPKBCFG.h"
#include "PKB.h"
#include "Type.h"
#include <iostream>
#include <string>

void PKBCFGTest::setUp(){
}

void PKBCFGTest::tearDown(){
}

/*
procedure Foo{
(01)	if x then{                     
(02)		x = 0;
(03)		while y{
(04)			x = 0;
(05)			y = 0;
(06)			if y then{
(07)				x = 0;
				}else{
(08)				z = 0;
				}
(09)			z = 1;
			}
		}else{
(10)		z = 0; 
		}
}
procedure Bar{
(11)	x = 0;
}
*/
void PKBCFGTest::testCreateAddGetCFG(){
	std::cout<<std::endl<<"PKB CreateCFG  ..."<<std::endl;
	PKB* pkbR = PKB::getInstance();
	//Set follow relationship
	CFG* cfgFoo = pkbR->createCFG(1);
	CPPUNIT_ASSERT(cfgFoo);
	CFG* cfgBar = pkbR->createCFG(2);
	CPPUNIT_ASSERT(cfgBar);
	std::cout<<std::endl<<"PKB Add to CFG Family  ..."<<std::endl;
	pkbR->addToCFGFamily(cfgFoo);
	pkbR->addToCFGFamily(cfgBar);
	std::cout<<std::endl<<"PKB Get CFG by proc index  ..."<<std::endl;
	CPPUNIT_ASSERT(cfgFoo == pkbR->getCFGByProcedureIndex(1));
	CPPUNIT_ASSERT(cfgBar == pkbR->getCFGByProcedureIndex(2));
}
void PKBCFGTest::testCreateGetCFGNode(){
	PKB* pkbR = PKB::getInstance();
	TreeNode* tnode1 = new TreeNode(AST_IF);
	CFGNode* node1 = pkbR->createCFGNode(1, tnode1);
	CFGNode* node2 = pkbR->createCFGNode(2, new TreeNode(AST_ASSIGN));
	CFGNode* node3 = pkbR->createCFGNode(3, new TreeNode(AST_WHILE));
	CFGNode* node4 = pkbR->createCFGNode(4, new TreeNode(AST_ASSIGN));
	CFGNode* node5 = pkbR->createCFGNode(5, new TreeNode(AST_ASSIGN));
	CFGNode* node6 = pkbR->createCFGNode(6, new TreeNode(AST_IF));
	CFGNode* node7 = pkbR->createCFGNode(7, new TreeNode(AST_ASSIGN));
	CFGNode* node8 = pkbR->createCFGNode(8, new TreeNode(AST_ASSIGN));
	CFGNode* node9 = pkbR->createCFGNode(9, new TreeNode(AST_ASSIGN));
	CFGNode* node10 = pkbR->createCFGNode(10, new TreeNode(AST_ASSIGN));
	CFGNode* node11 = pkbR->createCFGNode(11, new TreeNode(AST_ASSIGN));
	CFGNode* endNode1 = pkbR->createCFGEndNode();
	CFGNode* endNode2 = pkbR->createCFGEndNode();
	CPPUNIT_ASSERT(node1);
	CPPUNIT_ASSERT(endNode1);
	std::cout<<std::endl<<"PKB SetCFGRoot ..."<<std::endl;
	pkbR->setCFGRoot(pkbR->getCFGByProcedureIndex(1),node1);
	pkbR->setCFGRoot(pkbR->getCFGByProcedureIndex(2),node11);
	std::cout<<std::endl<<"PKB GetCFGRoot ..."<<std::endl;
	CPPUNIT_ASSERT(pkbR->getCFGRootNode(pkbR->getCFGByProcedureIndex(1))==node1);
	std::cout<<std::endl<<"PKB LinkCFGNodes ..."<<std::endl;
	pkbR->linkCFGNodes(node1,node2);
	pkbR->linkCFGNodes(node1,node10);
	pkbR->linkCFGNodes(node2,node3);
	pkbR->linkCFGNodes(node3,node4);

	pkbR->linkCFGNodes(node4,node5);
	pkbR->linkCFGNodes(node5,node6);
	pkbR->linkCFGNodes(node6,node7);
	pkbR->linkCFGNodes(node6,node8);

	pkbR->linkCFGNodes(node7,node9);
	pkbR->linkCFGNodes(node8,node9);
	pkbR->linkCFGNodes(node9,node3);
	pkbR->linkCFGNodes(node9,endNode1);

	pkbR->linkCFGNodes(node10,endNode1);
	pkbR->linkCFGNodes(node11,endNode2);
	std::cout<<std::endl<<"PKB GetASTNodeFromCFG ..."<<std::endl;
	CPPUNIT_ASSERT(pkbR->getASTNodeFromCFG(node1) == tnode1);
	std::cout<<std::endl<<"PKB GetCFGNodeContent ..."<<std::endl;
	CPPUNIT_ASSERT(pkbR->getCFGNodeContent(node1) == 1);
	CPPUNIT_ASSERT(pkbR->getCFGNodeContent(endNode1) == -2);
	std::cout<<std::endl<<"PKB GetSuccessorsCFG ..."<<std::endl;
	CPPUNIT_ASSERT(pkbR->getSuccessorsCFG(node1).at(0) == node2);
	CPPUNIT_ASSERT(pkbR->getSuccessorsCFG(node6).size() == 2);
	std::cout<<std::endl<<"PKB GetPredecessorCFG ..."<<std::endl;
	CPPUNIT_ASSERT(pkbR->getPredecessorCFG(node3).size() == 2);
}